﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Networking.Sockets;
using Windows.Networking.Connectivity;
using Windows.ApplicationModel.DataTransfer;
using Windows.Networking;
using Windows.Storage.Streams;

namespace eLuk.CommandEngine
{
	public class Channel
	{
		public event ChannelLinkLoadCompleted ChannelLinkLoadCompleted;
		public event ChannelLinkConnected ChannelLinkConnected;

		public bool IsConnected { get; set; }
		private EmailClientCredential _credential { get; set; }

		public EmailServer Server { get; set; }

		public const uint MaxBufferSize = 1024 * 1024 * 15;

		public const uint MaxReadBufferSize = 1024;

		//private int _commandStartTick = 0;
		public int ConnectTimeout { get; set; }

		public Channel( EmailServer _server )
		{
			this.ChannelLinkConnected += Channel_ChannelLinkConnected;
			this.ChannelLinkLoadCompleted += Channel_ChannelLinkLoadCompleted;
			this.ConnectTimeout = 5000;
			this._credential = _server.Credential;
			this.Server = _server;
			//this.IsConnected = this.SetSocket();
			//this.IsConnected = this.SetSocketAsync().GetAwaiter().GetResult();
			//this.IsConnected = this.SetSocket().Result;

			//if ( this.Link == null || !this.IsConnected )
			//	throw new Exception( "Unable to open Channel.Link" );
		}

		public async Task<bool> SetSocketAsync()
		{
			//bool status = false;
			try
			{
				//HostName hostName = null;
				try
				{
					this.Server.HostName = new HostName( this.Server.Name );
					//hostName = new HostName( this.Server.Name );
					try
					{
						if ( this.Link == null || ( this.Link.Information.RemoteServiceName == "" ) )
						{
							this.Link = null;
							this.Link = new StreamSocket();
							//set write for your socket
							this.Writer = new DataWriter( this.Link.OutputStream );
							//set reader for your socket
							this.Reader = new DataReader( this.Link.InputStream );
							//define if partial reads are allowed
							this.Reader.InputStreamOptions = Windows.Storage.Streams.InputStreamOptions.Partial;
							//set Outbound buffer size
							this.Link.Control.OutboundBufferSizeInBytes = Channel.MaxBufferSize;
							//open connection
							//await this.Link.ConnectAsync( this.Server.HostName, this.Server.Port, SocketProtectionLevel.Ssl );
							await this.Link.ConnectAsync( this.Server.HostName, this.Server.Port, SocketProtectionLevel.Tls12 );
							ChannelLinkConnectedEventArgs connectedEvent = new ChannelLinkConnectedEventArgs();

							if ( this.ChannelLinkConnected != null )
							{
								this.ChannelLinkConnected( this.Link, connectedEvent );
							}

							//Misc.Delay( 5000 );
							//do
							//{ }
							//while ( this.Link.Information.RemoteHostName == null );
						}
					}
					catch ( Exception ex )
					{
						this.Link = null;
						return false;
					}
				}
				catch ( ArgumentException ex )
				{
					this.Link = null;
					return false;
				}
			}
			catch ( Exception ex )
			{
				this.Link = null;
				return false;
			}
			return true;
		}
		
		private bool CheckConnectionState()
		{
			bool status = false;

			try
			{
			}
			catch ( Exception ex )
			{
				string str = ex.Message;
			}
			return status;
		}

		public StreamSocket Link { get; set; }

		public Windows.Storage.Streams.DataReader Reader { get; set; }

		public Windows.Storage.Streams.DataWriter Writer { get; set; }

		private async void Channel_ChannelLinkConnected( object sender, ChannelLinkConnectedEventArgs e )
		{
			await this.Reader.LoadAsync( Channel.MaxBufferSize );
			ChannelLinkLoadCompletedEventArgs loadEvent = new ChannelLinkLoadCompletedEventArgs();
			loadEvent.Status = e.Status;
			if ( this.ChannelLinkLoadCompleted != null )
			{
				this.ChannelLinkLoadCompleted( sender, loadEvent );
			}
		}

		private void Channel_ChannelLinkLoadCompleted( object sender, ChannelLinkLoadCompletedEventArgs e )
		{
			string s = "";
			do
			{
				s = this.Reader.ReadLine().GetAwaiter().GetResult();
				if ( s != null )
				{
					if ( s.StartsWith( IMAPResponses.StarOK ) )
					{
						e.Status = true;
					}
				}
			}
			while ( this.Reader.UnconsumedBufferLength != 0 );
		}

	}

}
